package com.czi.webrtctemp
// Android 基础
import android.content.Context
import android.os.Handler
import android.os.Looper
import android.util.Log
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.webrtc.AudioTrack
import org.webrtc.Camera1Enumerator
import org.webrtc.DataChannel
import org.webrtc.DefaultVideoDecoderFactory
import org.webrtc.DefaultVideoEncoderFactory

// WebRTC 核心
import org.webrtc.EglBase
import org.webrtc.IceCandidate
import org.webrtc.MediaConstraints
import org.webrtc.MediaStream
import org.webrtc.MediaStreamTrack
import org.webrtc.PeerConnection
import org.webrtc.PeerConnectionFactory
import org.webrtc.RtpReceiver
import org.webrtc.RtpTransceiver
import org.webrtc.SessionDescription
import org.webrtc.SdpObserver  // 用于SDP回调
import org.webrtc.SurfaceTextureHelper
import org.webrtc.SurfaceViewRenderer
import org.webrtc.VideoCapturer
import org.webrtc.VideoTrack

// 协程
import kotlin.coroutines.suspendCoroutine
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException

// 结果封装
import kotlin.Result

// 创建精简的抽象类
private open class SimpleSdpObserver : SdpObserver {
    override fun onCreateSuccess(desc: SessionDescription) {}
    override fun onSetSuccess() {}
    override fun onCreateFailure(error: String) {}
    override fun onSetFailure(error: String) {}
}

class WebRTCClient(
    private val context: Context,
    private val eglBase: EglBase,
    private val signalingServer: String
) {
    companion object {
        private const val TAG = "WebRTC客户端"
        private const val VIDEO_WIDTH = 1280
        private const val VIDEO_HEIGHT = 720
        private const val FPS = 30

        private val ICE_SERVERS = listOf(
            PeerConnection.IceServer.builder("stun:stun.l.google.com:19302")
                .createIceServer(),
            PeerConnection.IceServer.builder("stun:stun1.l.google.com:19302")
                .createIceServer()
        )
    }

    private val handler = Handler(Looper.getMainLooper())
    private val peerConnectionFactory by lazy {
        Log.d(TAG, "正在初始化PeerConnection工厂...")
        createPeerConnectionFactory()
    }

    // 轨道状态
    private var peerConnection: PeerConnection? = null
    private var localVideoTrack: VideoTrack? = null
    private var localAudioTrack: AudioTrack? = null
    private var videoCapturer: VideoCapturer? = null
    private var surfaceTextureHelper: SurfaceTextureHelper? = null

    // ================== 初始化相关 ==================
    private fun createPeerConnectionFactory(): PeerConnectionFactory {
        Log.d(TAG, "创建PeerConnection工厂配置")
        val options = PeerConnectionFactory.InitializationOptions.builder(context)
            .setFieldTrials("WebRTC-UnifiedPlan/Enabled/")
            .createInitializationOptions()

        Log.d(TAG, "初始化原生PeerConnection工厂")
        PeerConnectionFactory.initialize(options)

        return PeerConnectionFactory.builder()
            .setOptions(PeerConnectionFactory.Options())
            .setVideoEncoderFactory(
                DefaultVideoEncoderFactory(
                    eglBase.eglBaseContext,
                    true,  // 启用Intel VP8编码器
                    true   // 启用H264高画质
                ).apply {
                    Log.d(TAG, "支持的编码格式: ${supportedCodecs.joinToString()}")
                }
            )
            .setVideoDecoderFactory(DefaultVideoDecoderFactory(eglBase.eglBaseContext))
            .createPeerConnectionFactory()
            .also { Log.d(TAG, "PeerConnection工厂创建成功") }
    }

    fun initializeLocalStream(localSurface: SurfaceViewRenderer) {
        Log.d(TAG, "正在初始化本地视频流...")
        handler.post {
            try {
                // 1. 初始化视频采集
                surfaceTextureHelper = SurfaceTextureHelper.create(
                    "视频采集线程",
                    eglBase.eglBaseContext
                ).also {
                    Log.d(TAG, "SurfaceTextureHelper创建完成")
                }

                val videoSource = peerConnectionFactory.createVideoSource(false).apply {
                    Log.d(TAG, "视频源创建完成")
                }

                videoCapturer = createCameraCapture().apply {
                    Log.d(TAG, "摄像头采集器创建完成")
                    initialize(
                        surfaceTextureHelper,
                        context,
                        videoSource.capturerObserver
                    )
                    startCapture(VIDEO_WIDTH, VIDEO_HEIGHT, FPS)
                    Log.d(TAG, "摄像头采集已启动 (分辨率:${VIDEO_WIDTH}x$VIDEO_HEIGHT 帧率:$FPS)")
                }

                // 2. 创建音视频轨道
                localVideoTrack = peerConnectionFactory.createVideoTrack(
                    "本地视频轨道",
                    videoSource
                ).apply {
                    addSink(localSurface)
                    Log.d(TAG, "本地视频轨道已创建并绑定到Surface")
                }

                localAudioTrack = peerConnectionFactory.createAudioTrack(
                    "本地音频轨道",
                    peerConnectionFactory.createAudioSource(MediaConstraints())
                ).also {
                    Log.d(TAG, "本地音频轨道创建完成")
                }

                Log.d(TAG, "本地视频流初始化完成")
            } catch (e: Exception) {
                Log.e(TAG, "本地视频流初始化失败", e)
                release()
                throw e
            }
        }
    }

    // ================== 通话管理 ==================
    suspend fun startCall(
        app: String,
        stream: String,
        remoteSurface: SurfaceViewRenderer
    ): Result<Unit> = withContext(Dispatchers.IO) {
        runCatching {
            Log.d(TAG, "正在发起通话: 应用[$app] 流[$stream]")

            // 2. 创建对等连接
            val pc = createPeerConnection(remoteSurface)
            requireNotNull(pc) { "创建 PeerConnection 失败" }
            peerConnection = pc
            Log.d(TAG, "对等连接创建成功")

            // 3. 添加本地轨道
            localVideoTrack?.let { track ->
                pc.addTrack(track, listOf("local_video_stream")).also { sender ->
                    Log.d(TAG, "视频发送器创建完成 参数:${sender.parameters}")
                }
            } ?: throw IllegalStateException("本地视频轨道未初始化")

            localAudioTrack?.let {
                pc.addTrack(it, listOf("local_audio_stream"))
                Log.d(TAG, "音频轨道添加完成")
            }

            // 4. 创建并交换SDP
            val offer = createOffer()
            Log.d(TAG, "本地Offer创建成功:\n$offer")

            SignalingClient.exchangeSDP(
                signalingServer,
                SdpExchangeModel(app, stream, "offer", offer)
            ).fold(
                onSuccess = { answer ->
                    Log.d(TAG, "收到远端Answer:\n$answer")
                    setRemoteSdp(answer)
                    Log.d(TAG, "远端SDP设置成功")
                },
                onFailure = { throw it }
            )

            Log.d(TAG, "通话建立成功")
            Unit
        }.onFailure { e ->
            Log.e(TAG, "通话建立失败", e)
            release()
        }
    }

    private fun createPeerConnection(remoteSurface: SurfaceViewRenderer): PeerConnection {
        Log.d(TAG, "正在创建对等连接配置")
        val config = PeerConnection.RTCConfiguration(ICE_SERVERS).apply {
            sdpSemantics = PeerConnection.SdpSemantics.UNIFIED_PLAN
            bundlePolicy = PeerConnection.BundlePolicy.MAXBUNDLE
            rtcpMuxPolicy = PeerConnection.RtcpMuxPolicy.REQUIRE
            continualGatheringPolicy = PeerConnection.ContinualGatheringPolicy.GATHER_CONTINUALLY
            iceTransportsType = PeerConnection.IceTransportsType.ALL
            Log.d(TAG, "对等连接配置: ${toString()}")
        }

        return peerConnectionFactory.createPeerConnection(
            config,
            object : PeerConnection.Observer {
                override fun onSignalingChange(newState: PeerConnection.SignalingState?) {
                    Log.d(TAG, "信令状态变更: $newState")
                }

                override fun onIceConnectionChange(newState: PeerConnection.IceConnectionState?) {
                    Log.d(TAG, "ICE连接状态变更: $newState")
                    when(newState) {
                        PeerConnection.IceConnectionState.CONNECTED ->
                            Log.d(TAG, "ICE连接已建立")
                        PeerConnection.IceConnectionState.DISCONNECTED ->
                            Log.w(TAG, "ICE连接断开")
                        PeerConnection.IceConnectionState.FAILED ->
                            Log.e(TAG, "ICE连接失败")
                        else -> {}
                    }
                }

                override fun onIceConnectionReceivingChange(receiving: Boolean) {
                    Log.d(TAG, "ICE连接接收状态: ${if(receiving) "可接收" else "不可接收"}")
                }

                override fun onIceGatheringChange(newState: PeerConnection.IceGatheringState?) {
                    Log.d(TAG, "ICE收集状态变更: $newState")
                }

                override fun onIceCandidate(candidate: IceCandidate?) {
                    Log.d(TAG, "发现新的ICE候选: ${candidate?.toString()}")
                }

                override fun onIceCandidatesRemoved(candidates: Array<out IceCandidate>?) {
                    Log.d(TAG, "移除ICE候选: ${candidates?.size}个")
                }

                override fun onConnectionChange(newState: PeerConnection.PeerConnectionState?) {
                    Log.d(TAG, "对等连接状态变更: $newState")
                    when(newState) {
                        PeerConnection.PeerConnectionState.CONNECTED ->
                            Log.d(TAG, "对等连接已建立")
                        PeerConnection.PeerConnectionState.DISCONNECTED ->
                            Log.w(TAG, "对等连接断开")
                        PeerConnection.PeerConnectionState.FAILED ->
                            Log.e(TAG, "对等连接失败")
                        else -> {}
                    }
                }

                // Unified Plan核心回调
                override fun onTrack(transceiver: RtpTransceiver) {
                    Log.d(TAG, """
                        收到远端轨道:
                        - 媒体ID: ${transceiver.mid}
                        - 媒体类型: ${transceiver.mediaType}
                        - 传输方向: ${transceiver.direction}
                        - 当前方向: ${transceiver.currentDirection}
                    """.trimIndent())

                    handler.post {
                        if (transceiver.mediaType == MediaStreamTrack.MediaType.MEDIA_TYPE_VIDEO) {
                            (transceiver.receiver.track() as? VideoTrack)?.let { track ->
                                Log.d(TAG, "正在将远端视频轨道绑定到Surface")
                                track.addSink(remoteSurface)
                                Log.d(TAG, "远端视频轨道绑定成功")
                            } ?: Log.e(TAG, "收到的视频轨道为空")
                        }
                    }
                }

                override fun onAddStream(stream: MediaStream?) {
                    Log.w(TAG, "收到旧版onAddStream回调(UnifiedPlan模式不应触发)")
                }

                override fun onRemoveStream(stream: MediaStream?) {
                    Log.d(TAG, "媒体流被移除: ${stream?.id}")
                }

                override fun onDataChannel(dataChannel: DataChannel?) {
                    Log.d(TAG, "数据通道已打开: ${dataChannel?.label()}")
                }

                override fun onRenegotiationNeeded() {
                    Log.d(TAG, "需要重新协商")
                }

                override fun onAddTrack(
                    receiver: RtpReceiver?,
                    streams: Array<out MediaStream>?
                ) {
                    Log.d(TAG, "通过旧版API添加轨道: ${receiver?.track()?.id()}")
                }
            }
        ) ?: throw IllegalStateException("创建对等连接失败").also {
            Log.e(TAG, "对等连接创建失败，配置参数: $config")
        }
    }

    // ================== 资源释放 ==================
    fun release() {
        Log.d(TAG, "正在释放资源...")
        handler.post {
            try {
                peerConnection?.let { pc ->
                    Log.d(TAG, "正在释放对等连接资源")
                    pc.dispose()
                    peerConnection = null
                }

                localVideoTrack?.let {
                    Log.d(TAG, "正在释放本地视频轨道")
                    it.dispose()
                    localVideoTrack = null
                }

                localAudioTrack?.let {
                    Log.d(TAG, "正在释放本地音频轨道")
                    it.dispose()
                    localAudioTrack = null
                }

                videoCapturer?.let { capturer ->
                    Log.d(TAG, "正在停止摄像头采集")
                    capturer.stopCapture()
                    capturer.dispose()
                    videoCapturer = null
                }

                surfaceTextureHelper?.let {
                    Log.d(TAG, "正在释放SurfaceTextureHelper")
                    it.dispose()
                    surfaceTextureHelper = null
                }

                Log.d(TAG, "所有资源已释放完毕")
            } catch (e: Exception) {
                Log.e(TAG, "资源释放过程中发生错误", e)
            }
        }
    }

    // ================== 内部工具方法 ==================
    private suspend fun createOffer(): String = suspendCoroutine { cont ->
        if (peerConnection == null) {
            cont.resumeWithException(Exception("PeerConnection未初始化"))
            return@suspendCoroutine
        }

        // 2. 检查媒体轨道
        val hasVideo = peerConnection?.senders?.any { it.track()?.kind() == "video" } ?: false
        if (!hasVideo) {
            cont.resumeWithException(Exception("未添加视频轨道"))
            return@suspendCoroutine
        }

        Log.d(TAG, "正在创建Offer...")
        peerConnection?.createOffer(object : SimpleSdpObserver() {
            override fun onCreateSuccess(desc: SessionDescription) {
                Log.d(TAG, "Offer创建成功")
                Log.d(TAG, "本地的的Offer SDP:\n${desc.description}")

                peerConnection?.setLocalDescription(object : SimpleSdpObserver() {
                    override fun onSetSuccess() {
                        Log.d(TAG, "本地描述设置成功")
                        cont.resume(desc.description)
                    }
                    override fun onSetFailure(error: String) {
                        Log.e(TAG, "设置本地描述失败: $error")
                        cont.resumeWithException(Exception(error))
                    }
                }, desc)
            }
            override fun onCreateFailure(error: String) {
                Log.e(TAG, "创建Offer失败: $error")
                cont.resumeWithException(Exception(error))
            }
        }, MediaConstraints().apply {
            mandatory.add(MediaConstraints.KeyValuePair("OfferToReceiveVideo", "true"))
            mandatory.add(MediaConstraints.KeyValuePair("OfferToReceiveAudio", "true"))
            mandatory.add(MediaConstraints.KeyValuePair("DtlsSrtpKeyAgreement", "true"))
        })
    }

    private suspend fun setRemoteSdp(sdp: String) = suspendCoroutine { cont ->
        Log.d(TAG, "正在设置远端SDP...")
        peerConnection?.setRemoteDescription(
            object : SimpleSdpObserver() {
                override fun onSetSuccess() {
                    Log.d(TAG, "远端SDP设置成功")
                    cont.resume(Unit)
                }
                override fun onSetFailure(error: String) {
                    Log.e(TAG, "设置远端SDP失败: $error")
                    cont.resumeWithException(Exception(error))
                }
            },
            SessionDescription(SessionDescription.Type.ANSWER, sdp)
        )
    }

    private fun createCameraCapture(): VideoCapturer {
        Log.d(TAG, "正在初始化摄像头采集器...")
        val enumerator = Camera1Enumerator(false)
        return enumerator.deviceNames.firstNotNullOfOrNull { deviceName ->
            enumerator.run {
                if (isBackFacing(deviceName)) {
                    createCapturer(deviceName, null).also {
                        Log.d(TAG, "使用后置摄像头: $deviceName")
                    }
                } else null
            }
        } ?: throw IllegalStateException("未找到可用摄像头").also {
            Log.e(TAG, "摄像头初始化失败：未找到可用摄像头")
        }
    }

    // ================== 状态检查方法 ==================
    fun logPeerConnectionState() {
        peerConnection?.let { pc ->
            Log.d(TAG, """
                对等连接当前状态:
                - 信令状态: ${pc.signalingState()}
                - ICE连接状态: ${pc.iceConnectionState()}
                - ICE收集状态: ${pc.iceGatheringState()}
                - 发送器数量: ${pc.senders.size}
                - 接收器数量: ${pc.receivers.size}
                - 收发器数量: ${pc.transceivers.size}
            """.trimIndent())
        } ?: Log.w(TAG, "对等连接未初始化")
    }
}